﻿using Microsoft.AspNet.Identity;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using System;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
using Yz.Base;
using Yz.Base.Constants;
using Yz.Base.Enums;
using Yz.Core.Extensions;
using Yz.Core.Tools;

namespace Yz.Mvc.Controllers
{
    [Authorize]
    public class BaseController : Controller
    {
        #region 登录授权
        protected IAuthenticationManager AuthenticationManager => HttpContext.GetOwinContext().Authentication;

        protected IOwinContext OwinContext => HttpContext.GetOwinContext();

        #endregion

        #region Excel导出
        /// <summary>
        /// Excel导出
        /// </summary>
        /// <param name="npoiExcel"></param>
        /// <param name="excelName"></param>
        protected void ExportExcel(NPOIExcel npoiExcel)
        {
            string fileExt = "";
            string contentType = "";
            if (npoiExcel.ExcelType == ExcelType.Xls)
            {
                fileExt = ExcelSuffix.Xls;
                contentType = "application/vnd.ms-excel";
            }
            else if (npoiExcel.ExcelType == ExcelType.Xlsx)
            {
                fileExt = ExcelSuffix.Xlsx;
                contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
            }
            npoiExcel.ExcelName = npoiExcel.ExcelName.Substring(0, npoiExcel.ExcelName.LastIndexOf("."));
            npoiExcel.ExcelName += fileExt;
            // 设置编码和附件格式   
            Response.ContentType = contentType;
            Response.ContentEncoding = Encoding.UTF8;
            Response.Charset = "GB2312";
            Response.AppendHeader("Content-Disposition",
                "attachment;filename=" + HttpUtility.UrlEncode(npoiExcel.ExcelName, Encoding.UTF8));
            Response.BinaryWrite(YzNPOI.ExportExcel(npoiExcel).GetBuffer());
            Response.End();
        }
        #endregion

        #region 用户属性
        /// <summary>
        /// 用户Id
        /// </summary>
        protected int UserId => User.Identity.GetUserId().ToInt();
        /// <summary>
        /// 用户姓名
        /// </summary>
        protected string UserName => User.Identity.GetUserName();
        #endregion

        #region 文件上传
        /// <summary>
        /// 文件根路径
        /// </summary>
        protected string FileRootPath
        {
            get
            {
                var dtNow = DateTime.Now;
                return "/File" + DateTime.Now.Year + "/" + dtNow.ToString("yyyyMMdd") + "/u" + UserId + "/";
            }
        }
        /// <summary>
        /// 临时文件根路径
        /// </summary>
        protected string TempFileRootPath
        {
            get
            {
                var dtNow = DateTime.Now;
                return "/FilesTemp/u" + UserId + "/" + dtNow.ToString("yyyyMM") + dtNow.ToString("yyyyMMdd") + "/";
            }
        }
        /// <summary>
        /// 合并文件
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="guid"></param>
        /// <returns></returns>
        protected VmUpFile MergeFile(string fileName, string guid)
        {
            var flExtension = fileName.Substring(fileName.LastIndexOf('.')).ToLower();
            var upFile = new VmUpFile();
            string tempFileRootPath = TempFileRootPath;
            var fileRootPath = FileRootPath;
            var tempFilePath = Server.MapPath("~" + tempFileRootPath + guid.Replace("-", "") + "/");
            if (!Directory.Exists(tempFilePath))
            {
                upFile.suc = false;
                upFile.msg = "文件上传失败！";
                upFile.chunk = false;
                return upFile;
            }
            var newFileName = DateTime.Now.ToString("yyyyMMddHHmmssfff");
            if (!Directory.Exists(Server.MapPath(fileRootPath)))
            {
                Directory.CreateDirectory(Server.MapPath(fileRootPath));
            }
            var targetPath = Path.Combine(Server.MapPath(fileRootPath), newFileName + flExtension);///合并后的文件路径

            var dcInfo = new DirectoryInfo(tempFilePath);
            var files = dcInfo.GetFiles();
            MergeTempFile(targetPath, files);
            if (files.Length == 0)
            {
                upFile.suc = false;
                upFile.msg = "文件上传失败！";
                return upFile;
            }

            upFile.suc = true;
            upFile.msg = "上传成功";
            upFile.File = new FileModel()
            {
                Name = fileName,
                Path = fileRootPath + newFileName + flExtension,
                FileSuffix = flExtension,
                FileType = FileType.Vdo,
                ThPath = FileThPath.Vdo
            };
            return upFile;
        }

        /// <summary>
        /// 合并临时文件
        /// </summary>
        /// <param name="targetPath"></param>
        /// <param name="files"></param>
        private void MergeTempFile(string targetPath, FileInfo[] files)
        {
            foreach (var file in files.OrderBy(f => int.Parse(f.Name)))
            {
                using (var addFile = new FileStream(targetPath, FileMode.Append, FileAccess.Write))
                {
                    using (var AddWriter = new BinaryWriter(addFile))
                    {
                        //获得上传的分片数据流
                        using (Stream stream = file.Open(FileMode.Open))
                        {
                            using (var TempReader = new BinaryReader(stream))
                            {
                                //将上传的分片追加到临时文件末尾
                                AddWriter.Write(TempReader.ReadBytes((int)stream.Length));
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// 保存大文件
        /// </summary>
        /// <param name="chunk"></param>
        /// <param name="guid"></param>
        /// <param name="file"></param>
        /// <returns></returns>
        protected VmUpFile SaveBigFile(int chunk, string guid, HttpPostedFileBase file)
        {
            //当前分片在上传分片中的顺序（从0开始） 
            var upFile = new VmUpFile();
            string tempFileRootPath = TempFileRootPath;
            var localPath = Server.MapPath("~" + tempFileRootPath + guid.Replace("-", "") + "/");
            if (!Directory.Exists(localPath))
            {
                Directory.CreateDirectory(localPath);
            }
            var flExtension = file.FileName.Substring(file.FileName.LastIndexOf('.')).ToLower();

            if (!FileTypeList.VdoList.Contains(flExtension))
            {
                upFile.suc = false;
                upFile.msg = "只能上传Mp4、mov格式的文件！";
                return upFile;
            }
            using (var addFile = new FileStream(localPath + chunk, FileMode.Append, FileAccess.Write))
            {
                using (var AddWriter = new BinaryWriter(addFile))
                {
                    using (var stream = file.InputStream)
                    {
                        using (var TempReader = new BinaryReader(stream))
                        {
                            //将上传的分片追加到临时文件末尾
                            AddWriter.Write(TempReader.ReadBytes((int)stream.Length));
                        }
                    }
                }
            }
            upFile.File = new FileModel()
            {
                FileSuffix = flExtension,
                FileType = FileType.Vdo,
                Name = file.FileName
            };
            upFile.msg = "分片上传中";
            upFile.suc = true;
            return upFile;
        }

        /// <summary>
        /// 保存文件
        /// </summary>
        /// <param name="ft"></param>
        /// <param name="file"></param>
        /// <returns></returns>
        protected VmUpFile SaveFile(FileType ft, HttpPostedFileBase file)
        {
            var upFile = new VmUpFile();
            //创建文件夹 
            string fileRootPath = FileRootPath;
            var localPath = Server.MapPath("~" + fileRootPath);
            if (!Directory.Exists(localPath))
            {
                Directory.CreateDirectory(localPath);
            }
            var flExtension = file.FileName.Substring(file.FileName.LastIndexOf('.')).ToLower();
            #region 文件格式判断

            if (ft == FileType.Pic) //图片，判断图片格式的有效性
            {
                if (!FileTypeList.ImgList.Contains(flExtension))
                {
                    upFile.suc = false;
                    upFile.msg = "只能上传jpg,jpeg,png,bmp,gif格式的图片！";
                    return upFile;
                }
            }
            else if (ft == FileType.Doc)
            {
                if (!FileTypeList.DocList.Contains(flExtension))
                {
                    upFile.suc = false;
                    upFile.msg = "只能上传pdf,ppt,word,excel格式的文档！";
                    return upFile;
                }
            }
            else if (ft == FileType.Vdo)
            {
                if (!FileTypeList.VdoList.Contains(flExtension))
                {
                    upFile.suc = false;
                    upFile.msg = "只能上传mp4、mov格式的视频！";
                    return upFile;
                }
            }
            else
            {
                upFile.suc = false;
                upFile.msg = "只能上传文档、图片和视频文件！";
                return upFile;
            }

            #endregion 文件格式有效性判断

            //保存原文件
            var newFileName = DateTime.Now.ToString("yyyyMMddHHmmssfff");
            var filePath = string.Format("{0}{1}{2}", fileRootPath, newFileName, flExtension);
            var fileLocalPath = string.Format("{0}{1}{2}", localPath, newFileName, flExtension);

            var fileThPath = ""; //缩略图路径
            upFile.suc = true;

            #region 图片

            if (FileTypeList.ImgList.Contains(flExtension)) //保存缩略图
            {
                var newThumbnailFileName = newFileName + "_th";
                fileThPath = string.Format("{0}{1}{2}", fileRootPath, newThumbnailFileName, flExtension);
                var thFileLocalPath = string.Format("{0}{1}{2}", localPath, newThumbnailFileName, flExtension);
                file.InputStream.SaveImage(fileLocalPath, thFileLocalPath);
            }

            #endregion  

            else
            {
                file.SaveAs(fileLocalPath); //保存原文件

                #region 文档
                if (flExtension == ".pdf")
                {
                    fileThPath = FileThPath.PDF;
                }
                else if (flExtension == ".doc" || flExtension == ".docx")
                {
                    fileThPath = FileThPath.Word;
                }
                else if (flExtension == ".ppt" || flExtension == ".pptx")
                {
                    fileThPath = FileThPath.PPT;
                }
                else if (flExtension == ".xls" || flExtension == ".xlsx")
                {
                    fileThPath = FileThPath.Excel;
                }
                #endregion  

                #region 视频文件

                else if (FileTypeList.VdoList.Contains(flExtension))
                {
                    fileThPath = FileThPath.Vdo;
                }

                #endregion 视频文件

                else
                {
                    upFile.suc = false;
                    upFile.msg = "只能上传文档、图片和视频！";
                }
            }
            upFile.suc = true;
            upFile.msg = "上传成功";
            upFile.File = new FileModel()
            {
                Name = file.FileName,
                FileSuffix = flExtension,
                ThPath = fileThPath,
                FileType = ft,
                Path = filePath
            };
            return upFile;
        }

        /// <summary>
        /// 保存临时文件
        /// </summary>
        /// <param name="ft"></param>
        /// <param name="file"></param>
        /// <returns></returns>
        protected VmUpFile SaveTempFile(FileType ft, HttpPostedFileBase file)
        {
            var upFile = new VmUpFile();
            string tempFileRootPath = TempFileRootPath;
            var localPath = Server.MapPath("~" + tempFileRootPath);
            if (!Directory.Exists(localPath))
            {
                Directory.CreateDirectory(localPath);
            }
            var flExtension = file.FileName.Substring(file.FileName.LastIndexOf('.')).ToLower();

            #region 文件格式有效性判断

            if (ft == FileType.Pic) //图片，判断图片格式的有效性
            {
                if (!FileTypeList.ImgList.Contains(flExtension))
                {
                    upFile.suc = false;
                    upFile.msg = "只能上传jpg,jpeg,png,bmp,gif格式的图片！";
                    return upFile;
                }
            }
            else if (ft == FileType.Doc)
            {
                if (!FileTypeList.DocList.Contains(flExtension))
                {
                    upFile.suc = false;
                    upFile.msg = "只能上传pdf,doc,docx格式的文档！";
                    return upFile;
                }
            }
            else if (ft == FileType.Vdo)
            {
                upFile.suc = false;
                upFile.msg = "只能上传mp4,mov格式的视频！";
                return upFile;
            }
            else
            {
                upFile.suc = false;
                upFile.msg = "只能上传文档、图片和视频！";
                return upFile;
            }

            #endregion 文件格式有效性判断

            //保存原文件
            var newFileName = DateTime.Now.ToString("yyyyMMddHHmmssfff");
            var filePath = string.Format("{0}{1}{2}", tempFileRootPath, newFileName, flExtension);
            var fileLocalPath = string.Format("{0}{1}{2}", localPath, newFileName, flExtension);
            file.SaveAs(fileLocalPath); //保存原文件
            upFile.suc = true;
            upFile.msg = "上传成功";
            upFile.File = new FileModel()
            {
                Name = file.FileName,
                Path = filePath,
                FileSuffix = flExtension,
                FileType = ft
            };
            return upFile;
        }
        #endregion

        #region 验证码
        /// <summary>
        /// 获得验证码
        /// </summary>
        /// <returns></returns>
        public string GetSessionCheckCode()
        {
            string checkCode = "";
            var sessCode = Session[BaseSessionConstant.CheckCode];
            if (sessCode != null)
            {
                checkCode = sessCode.ToString();
            }
            return checkCode;
        }
        /// <summary>
        /// 移除验证码
        /// </summary>
        protected void RemoveSessionCheckCode()
        {
            Session.Remove(BaseSessionConstant.CheckCode);
        }
        /// <summary>
        /// 设置验证码
        /// </summary>
        /// <param name="checkCode"></param>
        protected void SetSessionCheckCode(string checkCode)
        {
            Session[BaseSessionConstant.CheckCode] = checkCode;
        }
        /// <summary>
        /// 验证验证码是否正确
        /// </summary>
        /// <param name="checkCode"></param>
        /// <returns></returns>
        protected bool ValidateCheckCode(string checkCode)
        {
            string sessionCode = GetSessionCheckCode();
            return checkCode.ToLower() == sessionCode.ToLower();
        }
        #endregion

        #region Ip
        /// <summary>
        /// 获得客户端Ip
        /// </summary>
        /// <returns></returns>
        protected string GetClientIp()
        {
            string clientIp = BaseDefaultConstant.ClientIp;
            try
            {
                if (Request.ServerVariables == null)
                    return "";
                string CustomerIP = "";
                CustomerIP = Request.Headers["Cdn-Src-Ip"];
                if (!string.IsNullOrEmpty(CustomerIP))
                {
                    return CustomerIP;
                }
                CustomerIP = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
                if (!String.IsNullOrEmpty(CustomerIP))
                    return CustomerIP;
                if (Request.ServerVariables["HTTP_VIA"] != null)
                {
                    CustomerIP = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
                    if (CustomerIP == null)
                        CustomerIP = Request.ServerVariables["REMOTE_ADDR"];
                }
                else
                {
                    CustomerIP = Request.ServerVariables["REMOTE_ADDR"];
                }
                if (string.Compare(CustomerIP, "unknown", true) == 0)
                    return Request.UserHostAddress;
                return CustomerIP;
            }
            catch (Exception ex)
            {
                YzNLog.Error(ex);
            }
            return clientIp;
        }
        #endregion
    }
}